#pragma once
#include <string>
#include <unordered_map>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <strings.h>
class User
{
public:
    User() = default;
    User(const std::string &ip, const uint16_t &port)
        :ip_(ip), port_(port)
    {}
    
    std::string getIp() const 
    {
        return ip_;
    }
    uint16_t getPort() const
    {
        return port_;
    } 
private:
    std::string ip_;
    uint16_t port_;
};


class OnlineUser
{
public:
    void addUser(const std::string& ip, const uint16_t &port)
    {
        std::string name = ip + "-" + std::to_string(port);
        User user(ip, port);
        online_.emplace(name, user);
    }
    void delUser(const std::string& ip, const uint16_t &port)
    {
        std::string name = ip + "-" + std::to_string(port);
        if(online_.count(name))
        {
            online_.erase(name);
        }
    }

    bool isOnline(const std::string& ip, const uint16_t &port)
    {
        std::string name = ip + "-" + std::to_string(port);
        return online_.count(name);
    }

    void broadCast(int sockfd, const std::string& ip, const uint16_t &port, const std::string& message)
    {
        std::string name = ip + "-" + std::to_string(port);
        
        std::string broadMessage = "[" + name + "]# " + message;
        for(const auto& e : online_)
        {
            sockaddr_in client;
            socklen_t len = sizeof(client);
            bzero(&client, len);
            client.sin_family = AF_INET;
            client.sin_addr.s_addr = inet_addr(e.second.getIp().c_str());
            client.sin_port = htons(e.second.getPort());
            sendto(sockfd, broadMessage.c_str(), broadMessage.size(), 0, (const sockaddr*)&client, len);
        }
    }
    
private:
    std::unordered_map<std::string, User> online_;
};